#include"passwd.h"

struct user_session *sessions = NULL;

/**
 * @brief 将用户会话添加到会话列表中
 * 
 * 该函数会为新的用户会话分配内存，复制用户名，并将其添加到全局的用户会话哈希表中。
 * 如果内存分配失败，会输出错误信息并终止操作。
 * 
 * @param fd 客户端的文件描述符，用于唯一标识一个连接
 * @param username 要添加到会话列表的用户的用户名
 */
void add_session(int fd, const char *username, int pre_path) {
    // 为新的用户会话结构体分配内存
    struct user_session *s = (struct user_session *)malloc(sizeof(struct user_session));
    // 检查内存分配是否成功
    if (s == NULL) {
        // 若分配失败，输出错误信息
        perror("malloc failed");
        // 分配失败，直接返回
        return;
    }
    // 将客户端文件描述符赋值给用户会话结构体
    s->fd = fd;
    // 使用 strdup 函数将传入的用户名复制到堆上，并赋值给用户会话结构体
    s->username = strdup(username); 
    //pre_path
    s->pre_path = pre_path;
    // 检查用户名复制是否成功
    if (s->username == NULL) {
        // 若复制失败，输出错误信息
        perror("strdup failed");
        // 释放之前分配的用户会话结构体内存
        free(s);
        // 复制失败，直接返回
        return;
    }
    // 使用 HASH_ADD_INT 宏将新的用户会话添加到全局的会话哈希表中
    // sessions 是全局的会话哈希表，fd 是作为键的字段，s 是要添加的用户会话结构体
    HASH_ADD_INT(sessions, fd, s);
    // 记录日志，表明用户已成功添加到会话列表
    LOG_INFO("用户 %s 已添加到会话列表，FD = %d\n", username, fd);
}

struct user_session *find_session(int fd) {
    struct user_session *s;
    HASH_FIND_INT(sessions, &fd, s); 

    return s;
}

void delete_session(int fd) {
    struct user_session *s = find_session(fd);
    if (s) {
        HASH_DEL(sessions, s);
        free(s->username);
        free(s);
        LOG_INFO("用户会话 %d 已删除。\n", fd);
    }
}

void get_a_session(int fd,int pre_path,char *username) {
    struct user_session *s = find_session(fd);
    if (s) {
        // 打印用户会话的信息
        LOG_INFO("找到用户会话 %s: %d\n", s->username, fd);
        pre_path = s->pre_path;
        strcpy(username,s->username);
        LOG_INFO("用户 %s: %d 的pre_path为 %d\n",username, fd, pre_path);
        
    }
}

// // 假设你有一个处理客户端连接的函数
// void handle_client(int sockfd) {
//     char username_buffer[128];
//     char password_buffer[128];

//     // ... 接收客户端发送的用户名和密码 ...
//     // 假设 read_credentials 函数会填充 username_buffer 和 password_buffer
//     if (read_credentials(sockfd, username_buffer, sizeof(username_buffer), password_buffer, sizeof(password_buffer)) == 0) {
//         // ... 验证用户名和密码 ...
//         if (verify_user(username_buffer, password_buffer)) {
//             printf("用户 %s 认证成功，FD = %d\n", username_buffer, sockfd);
//             add_session(sockfd, username_buffer);
//             // ... 处理该用户的后续操作 ...
//         } else {
//             printf("用户认证失败，FD = %d\n", sockfd);
//             // ... 发送错误信息 ...
//             close(sockfd);
//         }
//     } else {
//         close(sockfd);
//     }
// }

// // 在处理需要用户身份的操作时
// void handle_query_request(int sockfd, const char *query) {
//     struct user_session *session = find_session(sockfd);
//     if (session) {
//         printf("用户 %s 查询: %s\n", session->username, query);
//         // ... 使用 session->username 进行数据库查询 ...
//     } else {
//         printf("FD %d 没有找到对应的用户会话。\n", sockfd);
//         // ... 处理错误 ...
//         close(sockfd); // 可选：关闭未知的连接
//     }
// }

// 在连接关闭时调用
void cleanup_connection(int sockfd) {
    delete_session(sockfd);
    close(sockfd);
    printf("连接 %d 已关闭，会话信息已清理。\n", sockfd);
    LOG_INFO("连接 %d 已关闭，会话信息已清理。\n", sockfd);
}

int change_session_prepath(int fd, int pre_path) {
    struct user_session *session = find_session(fd);
    if (session) {

        // char temp[1024] = {0};
        // // 释放原有的用户名内存
        // if (session->username) {
        //     strcpy(temp, session->username);
        //     free(session->username);
        //     session->username = NULL;
        // }

        // // 分配新的内存并复制新的用户名
        // session->username = strdup(temp);
        session->pre_path = pre_path;
        if (session->username == NULL) {
            perror("strdup failed");
            // 恢复 username 为 NULL 以避免悬挂指针
            session->username = NULL;
            return -1;
        }

        LOG_INFO("用户会话 %s: %d 的用户名已更改为 %d\n",session->username, fd, pre_path);
        return 0;
    } else {
        LOG_INFO("FD %d 没有找到对应的用户会话，无法更改prepath。\n", fd);
        return -1;
    }
}


